package com.ea.config;





import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ea.common.node.MenuNode;
import com.ea.common.utils.ToolUtil;
import com.ea.modular.model.sys.ShiroUser;
import com.ea.modular.model.sys.User;
import com.ea.modular.service.sys.UserService;
import com.ea.modular.utils.sys.SpringUtil;
import com.ea.modular.utils.sys.UserUtil;







/**
 * 自定义认证拦截器
 * @author jun
 *
 */

public class MyShiroRealm extends AuthorizingRealm {
	
	private static final Logger log = LoggerFactory.getLogger("adminLogger");

	/**
	 * realm的认证方法，从数据库查询用户信息
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;

		
		// token是用户输入的用户名和密码 
		// 第一步从token中取出用户名
		String username = usernamePasswordToken.getUsername();
		User u= new User();
		u.setLoginName(username);
		u.setDelFlag("0");
		// 第二步：根据用户输入的userCode从数据库查询
		UserService userService = SpringUtil.getBean(UserService.class);
		User user = userService.get(u);
		if (user == null) {
			throw new UnknownAccountException("用户名不存在");
			
		}
		
		
        // 从数据库查询到密码
		if (!user.getPassword().equals(userService.passwordEncoder(new String(usernamePasswordToken.getPassword()),user.getId()))) {
			throw new IncorrectCredentialsException("密码错误");
		}

		if (!user.getUseable().equals("1")) {
			throw new IncorrectCredentialsException("无效状态，请联系管理员");
		}
		
		
		
		
		//制作shrio模型存入session
		ShiroUser shiroUser = new ShiroUser();
        shiroUser.setId(user.getId());
        shiroUser.setName(user.getName());
        shiroUser.setLoginName(user.getLoginName());
        shiroUser.setOfficeId(user.getOfficeId());
        List<String> roleIds = UserUtil.getRoleIDS(user.getId());
		List<MenuNode> menus = new ArrayList<MenuNode>();
		if(ToolUtil.isNotEmpty(roleIds)){
			shiroUser.setRoleList(roleIds);
			shiroUser.setRoleName(UserUtil.getRoleNames(roleIds));
			menus=UserUtil.getMenusByRoleIds(roleIds);
			Set<String> permissions = UserUtil.getPermissionByRoleIds(roleIds);
			shiroUser.setPermissions(permissions);
			shiroUser.setMenus(menus);
		}else {
			throw new IncorrectCredentialsException("该用户没有权限,请联系管理员");
		}
		
		//存入session
		UserUtil.setUserSession(shiroUser);
     
		//将activeUser设置simpleAuthenticationInfo密码加盐操作
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(),
				ByteSource.Util.bytes(user.getId()), getName());

		

		
		return authenticationInfo;

	}

	/**
	 * 授权操作
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		log.debug("权限配置");
	
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		ShiroUser shiroUser = UserUtil.getCurrentUser();
	
        //设置包含哪些角色名
		authorizationInfo.setRoles(shiroUser.getRoleName());
		//设置按钮级的权限
		Set<String> permissions = new HashSet<String>();
		Set<String> ps = shiroUser.getPermissions();
		for (String str : ps) {
			if(ToolUtil.isNotEmpty(str)) {
				permissions.add(str);
			}
		}
		authorizationInfo.setStringPermissions(permissions);

		return authorizationInfo;
	}

	/**
	 * 重写缓存key，否则集群下session共享时，会重复执行doGetAuthorizationInfo权限配置
	 */
	@Override
	protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
		SimplePrincipalCollection principalCollection = (SimplePrincipalCollection) principals;
		Object object = principalCollection.getPrimaryPrincipal();

		if (object instanceof User) {
			User user = (User) object;

			return "authorization:cache:key:users:" + user.getId();
		}

		return super.getAuthorizationCacheKey(principals);
	}

}
